import os
from typing import Annotated, Any, Dict, Generic, Optional, TypeVar
from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field

from send_message.common.config import load_config
from send_message.common.logger import get_logger
from send_message.services.feishu_sdk import FeishuSDK

config = load_config("config.yaml")

# 初始化 FastMCP 服务
mcp = FastMCP("feishu_gongdan", description="飞书工单 MCP服务", version="1.0.0",host="0.0.0.0", port=9099)
sdk = FeishuSDK(config=config, logger=get_logger(name="wp_sdk"))
logger = get_logger(name="feishu_gongdan")

T = TypeVar("T")

class ApiResponse(BaseModel, Generic[T]):
    success: bool
    data: Optional[T] = None
    error: Optional[str] = None
    meta: Optional[Dict[str, Any]] = None

    @classmethod
    def ok(cls, data: T, meta: Dict[str, Any] = None) -> "ApiResponse[T]":
        return cls(success=True, data=data, meta=meta)

    @classmethod
    def fail(cls, error: str, meta: Dict[str, Any] = None) -> "ApiResponse[None]":
        return cls(success=False, error=error, meta=meta)

# MCP Prompt
@mcp.prompt(name="assistant", description="你是一个工单发送助手, 对特定的人发送工单")
def weather_assistant(query: str) -> str:
    return (
        "你是工单发送助手, 支持手机号码查询open_id, 并向open_id发送工单信息." \
        "发送成功一次即可停止. 无需多次发送."
        f"用户需求：{query}"
    )

@mcp.tool(name="query_openid", description="根据电话号码查询open_id")
async def query_openid(
    tel_number: Annotated[str, Field(description="用户的电话号码")],
) -> ApiResponse:
    """
    查询open_id
    Args:
        tel_number (str): 电话号码
    Returns:
        ApiResponse: 查询结果
    """
    logger.info(f"Querying open_id: tel_number={tel_number}")
    try:
        result = await sdk.query_openid(tel_number=tel_number)
        if not result:
            return ApiResponse.fail("查询结果为空，请检查日志。")
        logger.info(f"query_openid result: {result}")
        return ApiResponse.ok(data=result, meta={
            "tel_number": tel_number,
        })
    except Exception as e:
        logger.error(f"Error tel_number {tel_number}: {e}")
        return ApiResponse.fail(str(e))
    

@mcp.tool(name="send_message_by_phone", description="根据手机号发送工单消息")
async def send_message_by_phone(
    tel_number: Annotated[str, Field(description="用户手机号")],
    content: Annotated[str, Field(description="发送的工单内容")]
) -> ApiResponse:
    logger.info(f"Send message: tel_number={tel_number}, content={content}")
    try:
        # 查询 open_id
        openid_resp = await query_openid(tel_number)
        if not openid_resp.success or not openid_resp.data:
            return ApiResponse.ok(
                data={"status": "failed", "reason": "手机号查询 open_id 失败"},
                meta={"tel_number": tel_number}
            )
        
        open_id = openid_resp.data

        # 发送消息
        success = await sdk.send_message(open_id=open_id, content=content)
        if not success:
            return ApiResponse.ok(
                data={"status": "failed", "reason": "消息发送失败"},
                meta={"open_id": open_id}
            )

        return ApiResponse.ok(
            data=success,
            meta={"open_id": open_id}
        )
    except Exception as e:
        logger.error(f"Send message by phone failed: {e}")
        return ApiResponse.ok(
            data={"status": "failed", "reason": f"异常: {str(e)}"},
            meta={"tel_number": tel_number}
        )

    